(function ($) {
  // register namespace
  $.extend(true, window, {
    "Slick": {
      "GanttRangeSelector": GanttRangeSelector
    }
  });


  function GanttRangeSelector(options) {
    var _grid;
    var _gridOptions;
    var _$activeCanvas;
    var _dragging;
    
    var _decorators = [];
    var _self = this;
    var _handler = new Slick.EventHandler();
    var _defaults = {
      selectionCss: {
        "border": "2px dashed blue"
      }
    };

    // Frozen row & column variables
    var _rowOffset;
    var _columnOffset;
    var _isRightCanvas;
    var _isBottomCanvas;
    // stone start cell
    var _startCell;

    function init(grid) {
      options = $.extend(true, {}, _defaults, options);
      // _decorator = new Slick.GanttRangeDecorator(grid, options);
      _grid = grid;
      _gridOptions = _grid.getOptions();
      _handler
        .subscribe(_grid.onDragInit, handleDragInit)
        .subscribe(_grid.onDragStart, handleDragStart)
        .subscribe(_grid.onDrag, handleDrag)
        .subscribe(_grid.onDragEnd, handleDragEnd)
        .subscribe(_grid.onClick, function () {
         //  _decorator.hide();
        });
    }

    function destroy() {
      _handler.unsubscribeAll();
    }

    function handleDragInit(e, dd) {
      // Set the active canvas node because the decorator needs to append its
      // box to the correct canvas
      _$activeCanvas = $(_grid.getActiveCanvasNode(e));

      var c = _$activeCanvas.offset();

      _rowOffset = 0;
      _columnOffset = 0;
      _isBottomCanvas = _$activeCanvas.hasClass('grid-canvas-bottom');

      if (_gridOptions.frozenRow > -1 && _isBottomCanvas) {
        _rowOffset = (_gridOptions.frozenBottom) ? $('.grid-canvas-bottom').height() : $('.grid-canvas-top').height();
      }

      _isRightCanvas = _$activeCanvas.hasClass('grid-canvas-right');

      if (_gridOptions.frozenColumn > -1 && _isRightCanvas) {
        _columnOffset = $('.grid-canvas-left').width();
      }

      // prevent the grid from cancelling drag'n'drop by default
      e.stopImmediatePropagation();
    }

    function handleDragStart(e, dd) {
      //_decorator.hide();
      var temp = new Slick.GanttRangeDecorator(grid, options);
      _decorators.push(temp);
      var cell = _grid.getCellFromEvent(e);
      if (_self.onBeforeCellRangeSelected.notify(cell) !== false) {
        if (_grid.canCellBeSelected(cell.row, cell.cell)) {
          _dragging = true;
          e.stopImmediatePropagation();
        }
      }
      if (!_dragging) {
        return;
      }

      _grid.focus();
      dd.range = { start: cell, end: {} };
      _startCell = cell;

      return _decorators[_decorators.length - 1].show(new Slick.Range(cell.row, cell.cell), {
        start: _startCell.cell
      });
    }

    function handleDrag(e, dd) {
      if (!_dragging) {
        return;
      }
      e.stopImmediatePropagation();

      var end = _grid.getCellFromPoint(
        e.pageX - _$activeCanvas.offset().left + _columnOffset,
        e.pageY - _$activeCanvas.offset().top + _rowOffset
      );

      if ((!_grid.canCellBeSelected(end.row, end.cell))
        //|| (!_isRightCanvas && (end.cell > _gridOptions.frozenColumn))
        //|| (_isRightCanvas && (end.cell <= _gridOptions.frozenColumn))
        //|| ( !_isBottomCanvas && ( end.row >= _gridOptions.frozenRow ) )
        || (_isBottomCanvas && (end.row < _gridOptions.frozenRow))
      ) {
        return;
      }

      dd.range.end = end;
      var canvas = $(_grid.getActiveCanvasNode(e));
      _decorators[_decorators.length - 1].show(new Slick.Range(dd.range.start.row, dd.range.start.cell, end.row, end.cell), {
        start: _startCell.cell,
        canvas: canvas,
        end: dd.range.end.cell
      });
    }

    function handleDragEnd(e, dd) {
      if (!_dragging) {
        return;
      }
      var canvas = $(_grid.getActiveCanvasNode(e));
      // nsunleo 20210831 不去掉选中状态
      // stone TODO: 20220307 目前无法获取状态
      _decorators[_decorators.length - 1].dragEnd(new Slick.Range(
        dd.range.start.row,
        dd.range.start.cell,
        dd.range.end.row,
        dd.range.end.cell), {
        start: _startCell.cell,
        canvas: canvas,
        end: dd.range.end.cell
      }
      );

      _startCell = null;
      _dragging = false;
      e.stopImmediatePropagation();


      // _decorator.hide();
      _self.onCellRangeSelected.notify({
        range: new Slick.Range(
          dd.range.start.row,
          dd.range.start.cell,
          dd.range.end.row,
          dd.range.end.cell
        )
      });
    }

    $.extend(this, {
      "init": init,
      "destroy": destroy,

      "onBeforeCellRangeSelected": new Slick.Event(),
      "onCellRangeSelected": new Slick.Event()
    });
  }
})(jQuery);